/**
  ******************************************************************************
  * @file    power.c
  * @brief   This file provides code for the configuration
  *          of all used GPIO pins.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stdio.h"
#include "power.h"
#include "i2c.h"
#include "i2c_app.h"

void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
  int temp = 70000;
  if(GPIO_Pin == PCEI_RESET_LITE_Pin)
  {
    HAL_GPIO_WritePin(GPIOB, MCU_WDG_RSTN_Pin, GPIO_PIN_RESET);
    //HAL_Delay(1);
    while(temp > 1){temp--;}
    HAL_GPIO_WritePin(GPIOB, MCU_WDG_RSTN_Pin, GPIO_PIN_SET);
    printf("pr\n\r");
  }
}

void power_enable_delay(void)
{
	uint8_t power_address = MP5416_DEVICE_ADDR;
	uint8_t vol_value = 0xA8;
	uint8_t sysdisable = 0x00;

	HAL_GPIO_WritePin(GPIOA, EN_DVDD08_CPU_Pin|EN_DVDD08_APU_Pin, GPIO_PIN_SET);//
	//HAL_Delay(2);
	HAL_GPIO_WritePin(GPIOB, EN_3V3_SOC_Pin, GPIO_PIN_SET);//MP5426、MP8765
	
	///////////
	HAL_Delay(4);
	mp5416_write_reg(power_address,MP5416_VSET4,1,&sysdisable); //AVDD18_EMMC \DVDD18_IO\TAVDD18_IO
	HAL_Delay(6);
	mp5416_write_reg(power_address,MP5416_VSET4,1,&vol_value); 
	////////
	
	HAL_Delay(12);
	HAL_GPIO_WritePin(GPIOA, EN_DVDD08_PCIE_Pin, GPIO_PIN_SET);
	//HAL_Delay(3);
	HAL_GPIO_WritePin(GPIOB, EN_AVDD08_PCIE_Pin, GPIO_PIN_SET);
	HAL_Delay(5);//解复位
	HAL_GPIO_WritePin(GPIOB, MCU_WDG_RSTN_Pin, GPIO_PIN_SET);
}

void power_enable(void)
{
	HAL_GPIO_WritePin(GPIOA, EN_DVDD08_CPU_Pin|EN_DVDD08_APU_Pin, GPIO_PIN_SET);//
	//HAL_Delay(2);
	HAL_GPIO_WritePin(GPIOB, EN_3V3_SOC_Pin, GPIO_PIN_SET);//MP5426、MP8765

	HAL_Delay(12);
	HAL_GPIO_WritePin(GPIOA, EN_DVDD08_PCIE_Pin, GPIO_PIN_SET);
	//HAL_Delay(3);
	HAL_GPIO_WritePin(GPIOB, EN_AVDD08_PCIE_Pin, GPIO_PIN_SET);
	HAL_Delay(5);//解复位
	HAL_GPIO_WritePin(GPIOB, MCU_WDG_RSTN_Pin, GPIO_PIN_SET);
}

void power_disable(void)
{
    mp5416_disable_vol();
	//HAL_GPIO_WritePin(GPIOB, EN_AVDD08_PCIE_Pin, GPIO_PIN_RESET);
	//HAL_GPIO_WritePin(GPIOA, EN_DVDD08_PCIE_Pin, GPIO_PIN_RESET);
	//HAL_Delay(3);
    HAL_GPIO_WritePin(GPIOB, EN_3V3_SOC_Pin, GPIO_PIN_RESET);//MP5426、MP8765
	HAL_GPIO_WritePin(GPIOA, EN_DVDD08_CPU_Pin|EN_DVDD08_APU_Pin, GPIO_PIN_RESET);
}

void soc_reset(void)
{
	HAL_GPIO_WritePin(GPIOB, MCU_WDG_RSTN_Pin, GPIO_PIN_RESET);
	HAL_Delay(2);//解复位
	HAL_GPIO_WritePin(GPIOB, MCU_WDG_RSTN_Pin, GPIO_PIN_SET);
}

static void mp5416_disable_vol(void)
{
	uint8_t power_address = MP5416_DEVICE_ADDR;
	uint8_t sysdisable = 0x00;
	mp5416_write_reg(power_address,MP5416_VSET8,1,&sysdisable);  //AVDD18_FUSE
	HAL_Delay(3);
	HAL_GPIO_WritePin(GPIOB, EN_AVDD08_PCIE_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, EN_DVDD08_PCIE_Pin, GPIO_PIN_RESET);
	HAL_Delay(3);
	mp5416_write_reg(power_address,MP5416_VSET3,1,&sysdisable);  //DVDD08\VDDCORE_EMMC\DVDDREF_PLL\DVDDPOST_PLL
	mp5416_write_reg(power_address,MP5416_VSET7,1,&sysdisable); //avddio_pcie	
	HAL_Delay(3);
	mp5416_write_reg(power_address,MP5416_VSET6,1,&sysdisable);  //VAA_PLL_DDR
	mp5416_write_reg(power_address,MP5416_VSET1,1,&sysdisable);  //DVDDQLP_DDR
	mp5416_write_reg(power_address,MP5416_VSET2,1,&sysdisable);  //dvddq_ddr
	HAL_Delay(3);
	mp5416_write_reg(power_address,MP5416_VSET4,1,&sysdisable); //AVDD18_EMMC \DVDD18_IO\TAVDD18_IO
	mp5416_write_reg(power_address,MP5416_VSET5,1,&sysdisable);  //AVDDHV_PLL
	HAL_Delay(3);
	
}

uint8_t mp5416_read_reg(int16_t power_address,int16_t Reg_addr)   //读指定寄存器1个字节
{
	uint8_t Pow_Data_Buffer;
	
	select_pca_channel(CHANNEL_0_MP5416);
 	if(HAL_I2C_Mem_Read(&hi2c2, ((power_address<<1)|0x01), Reg_addr, I2C_MEMADD_SIZE_8BIT,&Pow_Data_Buffer,1, 1000) != HAL_OK)
	{
		printf("power_read_reg failed\r\n");
		return 0xff;
	}

	return Pow_Data_Buffer;
}

void mp5416_write_reg(int16_t power_address,int16_t Reg_addr,int16_t snumber,uint8_t* Pow_Data_Buffer )
{
	select_pca_channel(CHANNEL_0_MP5416);

 	if(HAL_I2C_Mem_Write(&hi2c2, ((power_address<<1)|0x00), Reg_addr, I2C_MEMADD_SIZE_8BIT,Pow_Data_Buffer,snumber, 1000) != HAL_OK)
	{		
		printf("power_write_reg failed\r\n");
	}
}

void mp5416_init_vol(void)
{
	uint8_t power_address = MP5416_DEVICE_ADDR;
	uint8_t vol_value[8] = {0x80, 0x8C, 0x90, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8};
	
	mp5416_write_reg(power_address,MP5416_VSET1,8,vol_value); 
}

/*修改电压测试*/
void test_mp5416_set_vol(void)
{
	uint8_t power_address = MP5416_DEVICE_ADDR;
	uint8_t vol_value[8] = {0x83, 0x8C, 0x93, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8};
	
	mp5416_write_reg(power_address,MP5416_VSET1,8,vol_value); 
}

void mp5416_get_vol(uint8_t burk)
{
	uint8_t power_address = MP5416_DEVICE_ADDR;
	uint8_t read_vol = 0x00;
	
	read_vol = mp5416_read_reg(power_address,burk); 
	
}

void test_mp5416_get_vol(void)
{
	uint8_t power_address = MP5416_DEVICE_ADDR;
	uint8_t read_vol = 0x00;
	uint8_t i;
	float vol = 0;
	
	for(i = 0; i < 8; i++)
	{
		read_vol = mp5416_read_reg(power_address,MP5416_VSET1+i); 
		if (i == 0 || i == 2) //Buck1 and Buck3
		{	
			vol = (read_vol & 0x7F) * 0.0125 + 0.6;// clear MSB
			printf("Buck%d voltage: %fV\r\n",i + 1, vol);
		}
		else
		{
			vol = (read_vol & 0x7F) * 0.025 + 0.8;
			if (i == 1 || i == 3) // Buck2 and Buck4
				printf("Buck%d voltage: %fV\r\n", i + 1, vol);
			else
				printf("LDO%d voltage: %fV\r\n", i - 3, vol);
		}
	}
	printf("\r\n");
}


/*mp5416 reset*/
void power_reset(void)
{
	uint8_t power_address = MP5416_DEVICE_ADDR;
	uint8_t vol_value[2] = {0xC0,0x80};
	mp5416_write_reg(power_address,MP5416_CTL0,1,vol_value);   //0x00是否需要写，efuse如何选
	HAL_Delay(25);
	mp5416_write_reg(power_address,MP5416_CTL0,1,&vol_value[1]);   //0x00是否需要写，efuse如何选

}

/**************************************************************************************
INA220电压检测 
***************************************************************************************/
void ina220_read_config(uint16_t ina_addr)
{
	uint8_t INA3221_VOL_Data_Buffer[INA3221_VOL_NUMBER];

	select_pca_channel(CHANNEL_1_INA220);
	if(HAL_I2C_Mem_Read(&hi2c2, ((ina_addr<<1)|0x01), INA3221_CONFIG_ADDR, I2C_MEMADD_SIZE_8BIT,INA3221_VOL_Data_Buffer,INA3221_VOL_NUMBER, 1000) != HAL_OK)
	{
		printf("ina220_read_config failed\r\n");
	}

	printf("ina220_read_config 0x%x%x\n",INA3221_VOL_Data_Buffer[0],INA3221_VOL_Data_Buffer[1]);
	
}
float ina220_read_shuntv(uint16_t ina_addr)
{
	uint8_t INA3221_VOL_Data_Buffer[INA3221_VOL_NUMBER];
	int16_t ut;
	float shunt_value;

	select_pca_channel(CHANNEL_1_INA220);
	if(HAL_I2C_Mem_Read(&hi2c2, ((ina_addr<<1)|0x01), INA3221_SHUNTV_ADDR, I2C_MEMADD_SIZE_8BIT,INA3221_VOL_Data_Buffer,INA3221_VOL_NUMBER, 1000) != HAL_OK)
	{
		printf("ina220_read_shuntv failed\r\n");
	}

	ut = (int16_t)(((((uint16_t)INA3221_VOL_Data_Buffer[0]) << 8) | (uint16_t)INA3221_VOL_Data_Buffer[1]));
	
	//printf("ina220_read_shuntv 0x%x\n",(uint16_t)ut);

	shunt_value = (float)ut * 0.01; //lsb=0.01mv
	
	return shunt_value;
}

float ina220_read_busv(uint16_t ina_addr)
{
	uint8_t INA3221_VOL_Data_Buffer[INA3221_VOL_NUMBER];
	uint16_t ut;
	float bus_value;

	select_pca_channel(CHANNEL_1_INA220);
	if(HAL_I2C_Mem_Read(&hi2c2, ((ina_addr<<1)|0x01), INA3221_BUSV_ADDR, I2C_MEMADD_SIZE_8BIT,INA3221_VOL_Data_Buffer,INA3221_VOL_NUMBER, 1000) != HAL_OK)
	{
		printf("ina220_read_busv failed\r\n");
	}

	ut = (((uint16_t)INA3221_VOL_Data_Buffer[0]) << 8) | (uint16_t)INA3221_VOL_Data_Buffer[1];
	//printf("ina220_read_shuntv 0x%x\n",ut);

	ut = (ut >> 3) & (0x1fff);
	
	bus_value = (float)ut;
	bus_value *= 0.004; //v;lsb=4mv

	return bus_value;
}

int16_t ina220_read_power(uint16_t ina_addr)
{
	uint8_t INA3221_VOL_Data_Buffer[INA3221_VOL_NUMBER];
	int16_t ut;

	select_pca_channel(CHANNEL_1_INA220);
	if(HAL_I2C_Mem_Read(&hi2c2, ((ina_addr<<1)|0x01), INA3221_POWER_ADDR, I2C_MEMADD_SIZE_8BIT,INA3221_VOL_Data_Buffer,INA3221_VOL_NUMBER, 1000) != HAL_OK)
	{
		printf("ina220_read_power failed\r\n");
	}

	ut = (int16_t)(((((uint16_t)INA3221_VOL_Data_Buffer[0]) << 8) | (uint16_t)INA3221_VOL_Data_Buffer[1]));
	
	return ut;
}

int16_t ina220_read_current(uint16_t ina_addr)
{
	uint8_t INA3221_VOL_Data_Buffer[INA3221_VOL_NUMBER];
	int16_t ut;

	select_pca_channel(CHANNEL_1_INA220);
	if(HAL_I2C_Mem_Read(&hi2c2, ((ina_addr<<1)|0x01), INA3221_CURRENT_ADDR, I2C_MEMADD_SIZE_8BIT,INA3221_VOL_Data_Buffer,INA3221_VOL_NUMBER, 1000) != HAL_OK)
	{
		printf("ina220_read_current failed\r\n");
	}

	ut = (int16_t)(((((uint16_t)INA3221_VOL_Data_Buffer[0]) << 8) | (uint16_t)INA3221_VOL_Data_Buffer[1]));
	
	return ut;
}
void INA3221_Write_calibration(uint16_t ina_addr)
{
	uint8_t calibration_value[INA3221_VOL_NUMBER];

	//计算公式todo
	
	select_pca_channel(CHANNEL_1_INA220);
 	if(HAL_I2C_Mem_Write(&hi2c2, ((ina_addr<<1)|0x00), INA3221_CALIBRATION_ADDR, I2C_MEMADD_SIZE_8BIT,calibration_value,INA3221_VOL_NUMBER, 1000) != HAL_OK)
	{		
		printf("INA3221_Write_calibration failed\r\n");
	}
}

void inna_read_status(void)
{
	float VolReadValue;
	float VolReadBusValue;

	//ina220_read_config(INA3221_CPU_ADDR);
	//ina220_read_config(INA3221_APU_ADDR);
	//ina220_read_config(INA3221_PCIE_IN_ADDR);
	//ina220_read_config(INA3221_DVD08_ADDR);
	//ina220_read_config(INA3221_PCIE_ADDR);
	VolReadValue = ina220_read_shuntv(INA3221_CPU_ADDR);
	VolReadBusValue = ina220_read_busv(INA3221_CPU_ADDR);
	printf("CPU ShutValue1:%fmV\r\n", VolReadValue);
	printf("CPU BusValue1:%fV\r\n", VolReadBusValue);
	VolReadValue = ina220_read_shuntv(INA3221_APU_ADDR);
	VolReadBusValue = ina220_read_busv(INA3221_APU_ADDR);
	
	printf("APU ShutValue1:%fmV\r\n", VolReadValue);
	printf("APU BusValue1:%fV\r\n", VolReadBusValue);
	printf("APU power:%fW\r\n", VolReadBusValue*(VolReadValue/1.66667));
	VolReadValue = ina220_read_shuntv(INA3221_PCIE_IN_ADDR);
	VolReadBusValue = ina220_read_busv(INA3221_PCIE_IN_ADDR);
	//printf("PCIE_IN ShutValue1:%fmV\r\n", VolReadValue);
	printf("PCIE_IN Current:%fmV\r\n", VolReadValue/5);
	printf("PCIE_IN BusValue1:%fV\r\n", VolReadBusValue);
	VolReadValue = ina220_read_shuntv(INA3221_DVD08_ADDR);
	VolReadBusValue = ina220_read_busv(INA3221_DVD08_ADDR);
	printf("DVD08 ShutValue1:%fmV\r\n", VolReadValue);
	printf("DVD08 BusValue1:%fV\r\n", VolReadBusValue);
	VolReadValue = ina220_read_shuntv(INA3221_PCIE_ADDR);
	VolReadBusValue = ina220_read_busv(INA3221_PCIE_ADDR);
	printf("PCIE ShutValue1:%fmV\r\n", VolReadValue);
	printf("PCIE BusValue1:%fV\r\n", VolReadBusValue);
}



/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
